home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / cross / ava-0.2.5.lha / ava-0.2.5 / src / Main.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-23  |  6.4 KB  |  214 lines

  1. /*
  2.   Main.C
  3.   Algebraical Virtual Assembler
  4.   Uros Platise, Feb. 1998
  5. */
  6.  
  7. #include <sys/stat.h>
  8. #include <unistd.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. #include "Global.h"
  14. #include "Preproc.h"
  15. #include "Lexer.h"
  16. #include "Syntax.h"
  17. #include "Segment.h"
  18. #include "Symbol.h"
  19. #include "Keywords.h"
  20. #include "Reports.h"
  21. #include "Object.h"
  22. #include "Avr.h"
  23.  
  24.  
  25. const char* version = "AVA Version 0.2.5, Uros Platise";
  26. const char* arch_file = AVA_ARCH;
  27. const char* help = 
  28. "Syntax: ava [-pLv] [-Adevice] [-lI<filename>] [-I<dirname>] [-T{filename}]\n"
  29. "            [-Dmacro{=val}] [-fmacro{=val}] [-o outfile] files ...\n"
  30. "Files:\n"
  31. "  file.s     Assembler Source\n"
  32. "  file.o     Object; if not else specifed, this is the assembler default\n"
  33. "  a.out      Linker default output file name\n\n"
  34. "Switches:\n"
  35. "  -o         Set output file name (to redirect the output to stdout: -o"
  36. " stdout)\n"
  37. "  -p         Use stdin for input and stdout for output if -o is not set.\n"
  38. "  -A         Declare target device; same as: -Ddevice -Tarch.inc\n"
  39. "  -D         Define macro with value 'val'. If 'val' is not given 1 is"
  40. " assumed.\n"
  41. "  -f         Define public macro of the form __macro{=val}\n"
  42. "  -I         Add directory to the search list or include a file.\n"
  43. "  -T         Auto-include the 'target.inc' file or the 'filename' if given.\n"
  44. "             File specifed by the -T option is always first in the queue.\n"
  45. "\n"
  46. "  -L         Generate listing report (assembler only)\n"
  47. "  -v         Verbose (enable info)\n"
  48. "  -l         All reports, infos, errors and warnings are printed on the\n"
  49. "             stderr. If log file is specified info is redirected.\n"
  50. "             Errors and warnings are reported to the stderr and log file."
  51. "";
  52.  
  53.  
  54. TPreproc preproc;
  55. TLexer lexer;
  56. TGAS gas;
  57. TSyntax syntax;
  58. TSegment segment;
  59. TSymbol symbol;
  60. TKeywords keywords;
  61. TReports reports;
  62. TObject object;
  63. PArch archp;
  64.  
  65. int main(int argc, char* argv[]){
  66.   char ftype;
  67.   bool linker=false, assembler=false;
  68.   const char* include_targetfile=NULL;    /* always pushed last! */
  69.   char* outfile=NULL;
  70.   char* asmfile=NULL;
  71.   int ai;
  72.   TMicroStack<char *> files;
  73.   try{
  74.     for (ai=1; ai<argc; ai++){
  75.       ftype = argv[ai][strlen(argv[ai])-1];
  76.  
  77.       
  78.       if (argv[ai][0]=='-'){
  79.         if (argv[ai][2]==0){
  80.           switch(argv[ai][1]){
  81.         case 'h': printf("%s\n%s\n", version, help); exit(1);
  82.         case 'v': reports.IncVerboseLevel(); break;
  83.       case 'L': reports.listing.Enable(); break;
  84.           case 'T':
  85.         if (include_targetfile!=NULL){
  86.           throw generic_error("Target file already defined.");
  87.         }
  88.         include_targetfile=&argv[ai][2]; 
  89.         break;
  90.           case 'p': 
  91.             files.push("stdin"); outfile="stdout"; asmfile="stdin";
  92.             assembler=true; 
  93.             break;
  94.       case 'e': break;
  95.           case 'o': 
  96.         ai++; 
  97.             if (strstr(argv[ai],".s")!=NULL){
  98.               throw generic_error("Output file name has source extension"
  99.                 " `*.s'");
  100.             }
  101.             outfile=argv[ai];
  102.         break;      
  103.       default: throw generic_error("Invalid switch.");
  104.       }
  105.     }
  106.     else if (argv[ai][0]=='-' && argv[ai][1]=='-'){
  107.       if (strcmp(&argv[ai][2], "help")==0){
  108.         printf("%s\n%s\n", version, help); exit(1);
  109.       }
  110.       else{throw generic_error("Invalid switch.");}
  111.     }
  112.         else{
  113.           switch(argv[ai][1]){      
  114.       case 'l': reports.Config(&argv[ai][2]); break;
  115.       case 'D': {
  116.               char *val = strchr(&argv[ai][2],'=');
  117.               if (val==NULL){symbol.addMacro(&argv[ai][2],"1");}
  118.               else{
  119.                 char buf[LX_STRLEN]; int i=0; 
  120.                 while(val!=&argv[ai][i+2]){buf[i]=argv[ai][i+2];i++;} buf[i]=0;
  121.                 symbol.addMacro(buf,val+1);
  122.               }
  123.             } break;
  124.           case 'f': {
  125.               char *val = strchr(&argv[ai][2],'=');
  126.               char buf[LX_STRLEN]; strcpy(buf, "__");
  127.               if (val==NULL){
  128.                 strcat(buf, &argv[ai][2]); symbol.addMacro(buf,"1");
  129.               } else{
  130.                 int i=2; 
  131.                 while(val!=&argv[ai][i]){buf[i]=argv[ai][i];i++;} buf[i]=0;
  132.                 symbol.addMacro(buf,val+1,TSymbolRec::Public);
  133.               }
  134.             } break;
  135.       case 'I': {
  136.           struct stat file_info;
  137.           if (stat(&argv[ai][2], &file_info)<0){
  138.             throw file_error(&argv[ai][2]);
  139.           }
  140.           if (S_ISDIR(file_info.st_mode)){preproc.AddDir(&argv[ai][2]);}
  141.           else if (S_ISREG(file_info.st_mode)){files.push(&argv[ai][2]);}
  142.           else{
  143.             throw generic_error("Invalid file type for -I switch.");
  144.           }
  145.         } break;
  146.       case 'T':
  147.         if (include_targetfile!=NULL){
  148.           throw generic_error("Target file already defined.");
  149.         } 
  150.         include_targetfile=&argv[ai][2]; 
  151.         break;
  152.       case 'A':
  153.         if (include_targetfile!=NULL){
  154.           throw generic_error("Target file already defined.");
  155.         }
  156.         symbol.addMacro(&argv[ai][2],"1"); 
  157.         include_targetfile = arch_file;
  158.         break;
  159.       default: throw generic_error("Invalid switch.");
  160.           }
  161.     }
  162.       }else{      
  163.         switch(ftype){
  164.         case 's': 
  165.           if (assembler){
  166.         throw generic_error("Only one assembler source can"
  167.                             " be assembled at a time.");
  168.           }
  169.       assembler=true;
  170.           asmfile=argv[ai];
  171.       break;
  172.         case 'o': 
  173.           linker=true; 
  174.           files.push(argv[ai]); 
  175.           break;
  176.         default: throw generic_error("Unknown file type.");
  177.         }
  178.       }
  179.     }
  180.     
  181.     if (linker && assembler){ 
  182.       throw generic_error("Only assembler or linker can be invoked at a time.");
  183.     }
  184.     /* if assembler source was given, put it on the list as last */
  185.     if (assembler){files.push(asmfile);}
  186.     
  187.     /* resort files */
  188.     if (files.empty()){
  189.       fprintf(stderr,"%s: No input files.\n",argv[0]);exit(1);
  190.     }
  191.     while(!files.empty()){preproc.insert(files.pop());}
  192.  
  193.     if (assembler){
  194.       preproc.AddDir(AVA_LIB);
  195.       if (include_targetfile){
  196.         char buf[LX_STRLEN];
  197.         if (*include_targetfile==0){strcpy(buf,AVA_TARGET);}
  198.         else{strcpy(buf,include_targetfile);}
  199.         preproc.insert(preproc.FindFullPathName(buf));
  200.       }
  201.       object.assemble(outfile, asmfile);
  202.     }
  203.     if (linker){object.link(outfile);}
  204.   }
  205.   catch (segment_error &x){reports.Error(x);}
  206.   catch (lexer_error &x){reports.Error(x);}
  207.   catch (syntax_error &x){reports.Error(x);}
  208.   catch (file_error &x){reports.Error(x);}
  209.   catch (generic_error &x){reports.Error(x);}
  210.   
  211.   return reports.ErrorCount();
  212. }
  213.  
  214.